package com.ding.commander;

import com.ding.common.*;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Logger;

public class CPool extends Pool {

    private static Logger logger = Logger.getLogger("mynat");

    private Queue<Repeater> repeaters = new LinkedList<>();

    private int maxSize;

    int getMaxSize() {
        return maxSize;
    }

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    private int minSize;

    int getMinSize() {
        return minSize;
    }

    void setMinSize(int minSize) {
        this.minSize = minSize;
    }

    private int getWaiteTimeout;

    public void setGetWaiteTimeout(int getWaiteTimeout) {
        this.getWaiteTimeout = getWaiteTimeout;
    }

    public int getGetWaiteTimeout() {
        return getWaiteTimeout;
    }

    private CommanderChannelHolder commanderHolder;

    public void setCommanderHolder(CommanderChannelHolder commanderHolder) {
        this.commanderHolder = commanderHolder;
    }

    public boolean addOne(StreamChannel channel) {

        if (repeaters.size() + 1 > maxSize) {
            return false;
        }

        Repeater repeater = new Repeater();

        channel.setAfterCloseStrategy(() -> {
            repeaters.remove(repeater);
            Channel left = repeater.getLeft();
            if (left != null) {
                left.close(true);
            }
        });

        channel.setAfterCloseAnotherStrategy(() -> {
            if (!channel.isClosed()) {
                System.out.println("通信通道存在回收价值,回收通信通道");
                recycle(channel);
            }
        });

        //创建一个空白的通道
        StreamChannel streamChannel = new StreamChannel();

        repeater.setLeft(streamChannel);

        //设置为右侧通道
        repeater.setRight(channel);

        //单边开始流复制
        repeater.startRightToLeft();

        //放入到列表中
        repeaters.offer(repeater);

        synchronized (this) {
            this.notify();
        }

        super.add(channel);

        return true;
    }


    synchronized Repeater get() {

        if (repeaters.size() < minSize) {

            System.out.println("通道不足,创建新通道");

            commanderHolder.getCommander().sendNewStreamChannel(minSize - repeaters.size());
        }

        if (repeaters.size() == 0) {
            try {
                this.wait(getWaiteTimeout);
            } catch (InterruptedException ignore) {
            }
        }

        return repeaters.poll();
    }

    private Map<String, Waiter.TaskHolder> recycleTaskMap = new HashMap<>();

    //主动回收
    private void recycle(Channel socketHolder) {

        System.out.println("被回收通道的推荐者id:" + socketHolder.getIntroducerId());

        //直接关闭即可
        if (this.repeaters.size() + 1 > maxSize) {
            socketHolder.close();
            return;
        }

        //获取右侧通道

        //如果超时就直接关闭
        Waiter.TaskHolder timeout = Waiter.setTimeout(() -> {
            socketHolder.close();
            recycleTaskMap.remove(socketHolder.getId());
            logger.warning("通道回收失败,已被关闭");
        }, 2000);

        //将等待超时任务添加进map中
        recycleTaskMap.put(socketHolder.getId(), timeout);

        System.out.println("发送回收消息");
        //发出回收消息
        if (!commanderHolder.sendMsg(new Message().type(Constant.RECYCLE).id(socketHolder.getId()))) {
            socketHolder.close();
        }
    }

    //被动回收
    void recyclePassivity(String id) {

        Channel holder = getById(id);

        //如果已经关闭就不再执行
        if (holder.isClosed()) {
            return;
        }

        if (holder.getRepeater().getLeft() != null) {

            holder.getRepeater().getLeft().close(true);

            //添加
            if (repeaters.size() + 1 > maxSize) {
                holder.close();
                return;
            }

            //重新添加队列中
            synchronized (this) {
                repeaters.offer(holder.getRepeater());
                //唤醒线程
                this.notify();
            }

        }

    }

    //当回收成功的时候
    void recycleSuccess(String id) {
        Waiter.TaskHolder taskHolder = recycleTaskMap.remove(id);
        taskHolder.clear();
        Channel holder = getById(id);

        //添加
        if (repeaters.size() + 1 > maxSize) {
            holder.close();
            logger.info("回收通道时超出容量上限");
            return;
        }

        logger.info("成功回收通道");

        //重新添加队列中
        synchronized (this) {
            repeaters.offer(holder.getRepeater());
            //唤醒线程
            this.notify();
        }

    }

}
